package com.jinzhi.wxpay.controller;

import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import com.jinzhi.jzweb.service.JazCoursesOrderService;
import com.jinzhi.jzweb.service.JazUserOrderService;
import com.jinzhi.wxpay.enums.WechatPay2ValidatorForRequest;
import com.jinzhi.wxpay.service.WxPayService;
import com.jinzhi.wxpay.util.HttpUtils;
import com.jinzhi.wxpay.vo.R;
import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

/**
 *
 */
@CrossOrigin//跨域注解
@RestController
@RequestMapping("/api/wx-pay")
@Api(tags = "微信支付api")//这个是swagger的注解
@Slf4j
public class WxPayController {

        @Resource//注入这个类
        private WxPayService wxPayService;

        @Resource
        private Verifier  verifier;

        @Autowired
        private JazCoursesOrderService jazCoursesOrderService;



        /**
         *因为我们需要再小程序中使用微信支付，可能是直接购买积分
         * 因此可以不用传商品的订单，无需商品信息的判断
         *
         * */
        @ApiOperation("调用统一下单API，生成支付二维码")//swagger的注解
        @PostMapping("/native")
        public R nativePay(Long userId, Long  productId) throws Exception {//传入一个商品的id和用户id
            log.info("发起支付请求");
            //返回支付二维码链接和订单号
            Map<String,Object> map = wxPayService.nativePay(userId,productId);
            return  R.ok().setData(map);


        }

        /**
         * 小程序支付调用接口
         *  目前用于积分购买和充值
         * */
        @ApiOperation("调用统一下单API，实现小程序支付")//swagger的注解
        @PostMapping("/JsApinativePay")
        @ResponseBody
        public R JsApinativePay(String title, String openid, BigDecimal totalFee) throws Exception {//传入积分名（多少积分），用户id，订单金额，openid
            log.info("发起支付请求");
            //返回小程序支付所需参数
            Map<String,Object> map = wxPayService.JsApinativePay(title,openid,totalFee);
            return  R.ok().setData(map);
        }


        /**接收返回通知*/
        @PostMapping("/native/notify")
        @ResponseBody
        @Transactional//事务（不添加事务可能导致出错后支付没成功支付状态也被更改）
        public  String nativeNotify(HttpServletRequest request, HttpServletResponse response){
            //json转换工具
            Gson gson = new Gson();
            Map<String,String> map = new HashMap<>();//应答对象
            log.info("接收返回通知");
            try{
                //处理通知参数
                String body = HttpUtils.readData(request);
                Map<String,Object> bodyMap = gson.fromJson(body, HashMap.class);
                String requestId = (String)bodyMap.get("id");
                log.info("支付通知的id=====》 {}",bodyMap.get("id"));
                log.info("支付的通知完整数据 ====》",body);
                //微信支付应答（支付完成后给微信服务端进行应答）
                //ToDo:签名的验证
                WechatPay2ValidatorForRequest wechatPay2ValidatorForRequest = new WechatPay2ValidatorForRequest(verifier, requestId, body);
                if (!wechatPay2ValidatorForRequest.validate(request)){
                    log.error("通知验签失败");
                    response.setStatus(500);
                    map.put("code","ERROR");
                    map.put("message","通知验签失败");
                    return  gson.toJson(map);
                }
                log.error("通知验签成功");
                //ToDo:处理订单
                wxPayService.processOrder(bodyMap);

                //成功应答
                response.setStatus(200);
                map.put("code","SUCCESS");
                map.put("message","成功");
                return  gson.toJson(map);//微信规定通知返回值必须要为json字符串类型
            }catch (Exception e){
                e.printStackTrace();
                //失败应答
                response.setStatus(500);
                map.put("code","ERROR");
                map.put("message","失败");
                return  gson.toJson(map);
            }

        }

    /**
     * 支付返回消息通知
     * @param request
     * @param response
     * @return
     */
    @PostMapping("/native/notifys")
        @ResponseBody
        @Transactional
        public String notifys(HttpServletRequest request, HttpServletResponse response) {
            Gson gson = new Gson();
            Map<String, String> map = new HashMap<>();
            log.info("接收返回通知");

            try {
                // 处理通知参数
                String body = HttpUtils.readData(request);
                Map<String, Object> bodyMap = gson.fromJson(body, HashMap.class);
                String requestId = (String) bodyMap.get("id");
                log.info("支付通知的id: {}", requestId);
                log.info("支付的通知完整数据: {}", body);

                // 签名的验证
                WechatPay2ValidatorForRequest wechatPay2ValidatorForRequest = new WechatPay2ValidatorForRequest(verifier, requestId, body);
                if (!wechatPay2ValidatorForRequest.validate(request)) {
                    log.error("通知验签失败");
                    response.setStatus(500);
                    map.put("code", "ERROR");
                    map.put("message", "通知验签失败");
                    return gson.toJson(map);
                }

                log.info("通知验签成功");

                // 处理业务逻辑
                jazCoursesOrderService.processOrder(bodyMap);

                // 成功应答
                response.setStatus(200);
                map.put("code", "SUCCESS");
                map.put("message", "成功");
                return gson.toJson(map);
            } catch (Exception e) {
                log.error("处理支付通知时发生异常", e);
                // 失败应答
                response.setStatus(500);
                map.put("code", "ERROR");
                map.put("message", "失败");
                return gson.toJson(map);
            }
        }


    /**
     * 退款返回消息通知
     * @param request
     * @param response
     * @return
     */
        @PostMapping("/refunds/notifys")
        @ResponseBody
        @Transactional
        public String refundNotify(HttpServletRequest request, HttpServletResponse response) {
            Gson gson = new Gson();
            Map<String, String> map = new HashMap<>();
            log.info("接收退款通知");

            try {
                // 处理通知参数
                String body = HttpUtils.readData(request);
                Map<String, Object> bodyMap = gson.fromJson(body, HashMap.class);
                String requestId = (String) bodyMap.get("id");
                log.info("退款通知的id: {}", requestId);
                log.info("退款通知完整数据: {}", body);

                // 签名验证
                WechatPay2ValidatorForRequest wechatPay2ValidatorForRequest = new WechatPay2ValidatorForRequest(verifier, requestId, body);
                if (!wechatPay2ValidatorForRequest.validate(request)) {
                    log.error("通知验签失败");
                    response.setStatus(500);
                    map.put("code", "ERROR");
                    map.put("message", "通知验签失败");
                    return gson.toJson(map);
                }

                log.info("通知验签成功");

                // 处理业务逻辑，如更新订单状态为已退款
                jazCoursesOrderService.upOrderRefundStatus(bodyMap);

                // 成功应答
                response.setStatus(200);
                map.put("code", "SUCCESS");
                map.put("message", "成功");
                return gson.toJson(map);
            } catch (Exception e) {
                log.error("处理退款通知时发生异常", e);
                // 失败应答
                response.setStatus(500);
                map.put("code", "ERROR");
                map.put("message", "处理退款通知时发生异常");
                return gson.toJson(map);
            }
        }













    /**
     * 参与拼团支付返回消息通知
     * @param request
     * @param response
     * @return
     */
    @PostMapping("/native/cyGroupNotifys")
    @ResponseBody
    @Transactional
    public String cyGroupNotifys(HttpServletRequest request, HttpServletResponse response) {
        Gson gson = new Gson();
        Map<String, String> map = new HashMap<>();
        log.info("接收返回通知");

        try {
            // 处理通知参数
            String body = HttpUtils.readData(request);
            Map<String, Object> bodyMap = gson.fromJson(body, HashMap.class);
            String requestId = (String) bodyMap.get("id");
            log.info("支付通知的id: {}", requestId);
            log.info("支付的通知完整数据: {}", body);

            // 签名的验证
            WechatPay2ValidatorForRequest wechatPay2ValidatorForRequest = new WechatPay2ValidatorForRequest(verifier, requestId, body);
            if (!wechatPay2ValidatorForRequest.validate(request)) {
                log.error("通知验签失败");
                response.setStatus(500);
                map.put("code", "ERROR");
                map.put("message", "通知验签失败");
                return gson.toJson(map);
            }

            log.info("通知验签成功");

            // 处理业务逻辑
            jazCoursesOrderService.cyGroupProcessOrder(bodyMap);

            // 成功应答
            response.setStatus(200);
            map.put("code", "SUCCESS");
            map.put("message", "成功");
            return gson.toJson(map);
        } catch (Exception e) {
            log.error("处理支付通知时发生异常", e);
            // 失败应答
            response.setStatus(500);
            map.put("code", "ERROR");
            map.put("message", "失败");
            return gson.toJson(map);
        }
    }













    /**
     * 团购支付返回消息通知
     * @param request
     * @param response
     * @return
     */
    @PostMapping("/native/groupNotifys")
    @ResponseBody
    @Transactional
    public String groupNotifys(HttpServletRequest request, HttpServletResponse response) {
        Gson gson = new Gson();
        Map<String, String> map = new HashMap<>();
        log.info("接收返回通知");

        try {
            // 处理通知参数
            String body = HttpUtils.readData(request);
            Map<String, Object> bodyMap = gson.fromJson(body, HashMap.class);
            String requestId = (String) bodyMap.get("id");
            log.info("支付通知的id: {}", requestId);
            log.info("支付的通知完整数据: {}", body);

            // 签名的验证
            WechatPay2ValidatorForRequest wechatPay2ValidatorForRequest = new WechatPay2ValidatorForRequest(verifier, requestId, body);
            if (!wechatPay2ValidatorForRequest.validate(request)) {
                log.error("通知验签失败");
                response.setStatus(500);
                map.put("code", "ERROR");
                map.put("message", "通知验签失败");
                return gson.toJson(map);
            }

            log.info("通知验签成功");

            // 处理业务逻辑
            jazCoursesOrderService.groupProcessOrder(bodyMap);

            // 成功应答
            response.setStatus(200);
            map.put("code", "SUCCESS");
            map.put("message", "成功");
            return gson.toJson(map);
        } catch (Exception e) {
            log.error("处理支付通知时发生异常", e);
            // 失败应答
            response.setStatus(500);
            map.put("code", "ERROR");
            map.put("message", "失败");
            return gson.toJson(map);
        }
    }


    /**
     * 团购退款返回消息通知
     * @param request
     * @param response
     * @return
     */
    @PostMapping("/refunds/groupRefundNotify")
    @ResponseBody
    @Transactional
    public String groupRefundNotify(HttpServletRequest request, HttpServletResponse response) {
        Gson gson = new Gson();
        Map<String, String> map = new HashMap<>();
        log.info("接收退款通知");

        try {
            // 处理通知参数
            String body = HttpUtils.readData(request);
            Map<String, Object> bodyMap = gson.fromJson(body, HashMap.class);
            String requestId = (String) bodyMap.get("id");
            log.info("退款通知的id: {}", requestId);
            log.info("退款通知完整数据: {}", body);

            // 签名验证
            WechatPay2ValidatorForRequest wechatPay2ValidatorForRequest = new WechatPay2ValidatorForRequest(verifier, requestId, body);
            if (!wechatPay2ValidatorForRequest.validate(request)) {
                log.error("通知验签失败");
                response.setStatus(500);
                map.put("code", "ERROR");
                map.put("message", "通知验签失败");
                return gson.toJson(map);
            }

            log.info("通知验签成功");

            // 处理业务逻辑，如更新订单状态为已退款
            jazCoursesOrderService.upRefundStatus(bodyMap);

            // 成功应答
            response.setStatus(200);
            map.put("code", "SUCCESS");
            map.put("message", "成功");
            return gson.toJson(map);
        } catch (Exception e) {
            log.error("处理退款通知时发生异常", e);
            // 失败应答
            response.setStatus(500);
            map.put("code", "ERROR");
            map.put("message", "处理退款通知时发生异常");
            return gson.toJson(map);
        }
    }



}
